﻿@using Microsoft.CST.OAT.Blazor.Components;
@using Microsoft.CST.AttackSurfaceAnalyzer.Types
@using System.Threading;
@using Microsoft.CST.AttackSurfaceAnalyzer.Objects
@using Microsoft.CST.AttackSurfaceAnalyzer.Collectors
@inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData

@page "/guided"

<h4>Guided Mode</h4>
<div class="container-fluid bg-custom my-1 pb-1">
    @switch (pageState)
    {
        case PageState.Options:
            <div class="run-box bg-custom">
                <div class="form-inline">
                    <label class="mr-2" for="RunId">Run ID:</label>
                    <input type="text" class="form-control mr-2" id="RunId" placeholder="Enter Run ID" @bind="RunIdInput" />
                    <div class="form-check mr-2">
                        <input type="checkbox" class="form-check-input" id="UseTimestampCheckbox" @bind="UseTimestamp" />
                        <label class="form-check-label" for="UseTimestampCheckbox">Use Timestamp</label>
                    </div>
                    <button class="btn btn-primary" @onclick="BeginGuided">Start Guided Scan</button>
                </div>
            </div>
            <ul class="nav nav-tabs mb-3" id="options-tabs" role="tablist">
                <li class="nav-item">
                    <a class="nav-link active" id="collectors-tab" data-toggle="tab" href="#collectors" role="tab" aria-controls="collectors" aria-selected="true">Collectors</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="monitor-tab" data-toggle="tab" href="#monitor" role="tab" aria-controls="monitor" aria-selected="false">Monitor</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="analyze-tab" data-toggle="tab" href="#analyze" role="tab" aria-controls="analyze" aria-selected="false">Analyze</a>
                </li>
            </ul>
            <div class="tab-content" id="options-tabs-content">
                <div class="tab-pane fade show active" id="collectors" role="tabpanel" aria-labelledby="collectors-tab">
                    <CollectorOptionsRazor />
                </div>
                <div class="tab-pane fade" id="monitor" role="tabpanel" aria-labelledby="monitor-tab">
                    <MonitorOptionsRazor />
                </div>
                <div class="tab-pane fade" id="analyze" role="tabpanel" aria-labelledby="analyze-tab">
                    <AnalyzeOptionsRazor />
                </div>
            </div>

            break;
        case PageState.Scanning:
            <Scanning />
            break;
        case PageState.Monitoring:
            <Monitoring Continue="@ContinueGuided" />
            break;
        case PageState.MonitorFlushing:
            <MonitorFlushing />
            break;
        case PageState.Analyzing:
            <Analyzing />
            break;
        case PageState.Results:
            <Results FirstRunId="@appData.ExportCollectCommandOptions.FirstRunId" SecondRunId="@appData.ExportCollectCommandOptions.SecondRunId" AnalysesHash="@appData.CompareCommandOptions.AnalysesFile.GetHash()" MonitorRunId="@appData.MonitorOptions.RunId" />
            break;
        case PageState.Error:
            <p>An Error Occured while collecting.</p>
            break;
    }
</div>

@code{
    enum PageState
    {
        Options,
        Scanning,
        Monitoring,
        MonitorFlushing,
        Analyzing,
        Results,
        Error
    }

    bool UseTimestamp = true;
    string RunIdInput = "";

    PageState pageState = PageState.Options;

    async void BeginGuided()
    {
        appData.RunId = UseTimestamp ? DateTime.Now.ToString() : RunIdInput;
        timer = new System.Threading.Timer((_) => InvokeAsync(() => StateHasChanged()), null, 0, 100);
        appData.CollectOptions.RunId = appData.FirstRunId;
        if (await BeginScan() == ASA_ERROR.NONE)
        {
            appData.MonitorOptions.RunId = appData.MonitorRunId;
            await BeginMonitor();
            AttackSurfaceAnalyzerClient.ClearCollectors();
        }
        else
        {
            pageState = PageState.Error;
        }
    }

    async void ContinueGuided()
    {
        pageState = PageState.MonitorFlushing;
        this.StateHasChanged();
        AttackSurfaceAnalyzerClient.StopMonitors();
        while (AttackSurfaceAnalyzerClient.DatabaseManager.HasElements)
        {
            Thread.Sleep(1);
        }

        appData.CollectOptions.RunId = appData.SecondRunId;
        await BeginScan();

        appData.ExportCollectCommandOptions.SaveToDatabase = true;
        appData.ExportCollectCommandOptions.FirstRunId = appData.FirstRunId;
        appData.ExportCollectCommandOptions.SecondRunId = appData.SecondRunId;
        await BeginAnalyze();
        pageState = PageState.Results;
    }

    System.Threading.Timer timer;

    async Task<ASA_ERROR> BeginScan()
    {
        pageState = PageState.Scanning;
        this.StateHasChanged();
        return await Task.Factory.StartNew(() => AttackSurfaceAnalyzerClient.RunCollectCommand(appData.CollectOptions));
    }

    async Task<ASA_ERROR> BeginMonitor()
    {
        pageState = PageState.Monitoring;
        this.StateHasChanged();
        return await Task.Factory.StartNew(() => AttackSurfaceAnalyzerClient.RunGuiMonitorCommand(appData.MonitorOptions));
    }

    async Task<ASA_ERROR> BeginAnalyze()
    {
        pageState = PageState.Analyzing;

        await Task.Factory.StartNew(() =>
        {
            var CompareOneOptions = appData.CompareCommandOptions;
            CompareOneOptions.FirstRunId = appData.ExportCollectCommandOptions.FirstRunId;
            CompareOneOptions.SecondRunId = appData.ExportCollectCommandOptions.SecondRunId ?? string.Empty;
            var results = AttackSurfaceAnalyzerClient.CompareRuns(CompareOneOptions);
            AttackSurfaceAnalyzerClient.InsertCompareResults(results, appData.ExportCollectCommandOptions.FirstRunId, appData.ExportCollectCommandOptions.SecondRunId ?? string.Empty, appData.CompareCommandOptions.AnalysesFile?.GetHash() ?? "");
        });

        await Task.Factory.StartNew(() =>
        {
            var CompareTwoOptions = appData.CompareCommandOptions;

            CompareTwoOptions.FirstRunId = null;
            CompareTwoOptions.SecondRunId = appData.MonitorRunId;
            var results = AttackSurfaceAnalyzerClient.CompareRuns(CompareTwoOptions);
            AttackSurfaceAnalyzerClient.InsertCompareResults(results, null, appData.MonitorRunId, appData.CompareCommandOptions.AnalysesFile?.GetHash() ?? "");
        });
        return ASA_ERROR.NONE;
    }
}